<template>
    <div class="nut-swiper"
         :class="[direction,{'dragging':dragging}]"
         @touchstart = "_onTouchStart($event)"
         @mousedown = "_onTouchStart($event)"
    >
        <div class="nut-swiper-wrap"
             :style="{
                'transform':'translate3d('+translateX+'px,'+translateY+'px,0)',
                'transition-duration':transitionDuration+'ms',
                '-webkit-transform':'translate3d('+translateX+'px,'+translateY+'px,0)',
                '-webkit-transition-duration':transitionDuration+'ms',
                'transition-timing-function':'ease'
            }"
             @transitionend = "_onTransitionEnd"
        >
            <slot></slot>
        </div>
        <div class="nut-swiper-pagination" v-show="paginationVisible">
            <span class="swiper-pagination-bullet"
                  :class="{'active':index+1 === currentPage}"
                  v-for="(slide,index) in slideEls"
                  :key ="index"
                  @click="paginationClickable && setPage(index + 1,true)"
            >
            </span>
        </div>

    </div>
</template>
<script>
    const VERTICAL = 'vertical';
    const HORIZONTAL = 'horizontal';
    export default {
        name:"wioc-swiper",
        props:{
            direction:{
                type:String,
                default:HORIZONTAL,
                validator:(value) =>[VERTICAL,HORIZONTAL].indexOf(value)>-1
            },
            paginationVisible:{
                type:Boolean,
                default:false
            },
            paginationClickable:{
                type:Boolean,
                default:false
            },
            loop:{
                type:Boolean,
                default:false
            },
            speed:{
                type:Number,
                default:500
            },
            canDragging:{
                type:Boolean,
                default:true
            },
            autoPlay:{
                type:Number,
                default:0
            },
            initPage:{
                type:Number,
                default:1
            },
            lazyLoad:{
                type:Boolean,
                default:false
            },
            lazyLoadUrl:{
                type:String,
                default:'//img10.360buyimg.com/n1/s375x375_jfs/t1/811/7/9399/13031/5bab45c8E2614735e/a4e343007567442c.png'
            }
        },
        data(){
            return{
                dragging:false,
                currentPage:this.initPage,
                lastPage:1,
                translateX:0,
                translateY:0,
                startTranslate:0,
                slideEls:[],
                translateOffset:0,//当前偏移初始位置距离
                transitionDuration:0,//切换动画时间
                startPos:null,
                delta:0,//拖动距离
                startTime:null,
                isLoop:this.loop,
                timer:null,//自动播放定时器
                domTimer:null,//渲染延迟查找
                stopAutoPlay:false,//停止自动播放
                swiperWrap:null,
                oneSlideTranslate:0,//一个slide的大小
            }
        },
        methods:{
            //下一张
            next(){
                let page = this.currentPage;
                if(page < this.slideEls.length || this.isLoop){

                    this.setPage(page+1,true,'NEXT');
                }else{

                    this._revert();
                }
            },
            //上一张
            prev(){
                let page = this.currentPage;
                if(page > 1 || this.isLoop){
                    this.setPage(page-1,true,'PREV');
                }else{
                    this._revert();
                }
            },
            setPage(page,isHasAnimation,type){
                if(page === 0){
                    this.currentPage = this.slideEls.length;
                }else if(page === this.slideEls.length + 1){
                    this.currentPage = 1;
                }else{
                    this.currentPage = page;
                }
                this._setTranslate(this._getTranslateOfPage(page));
                if(!isHasAnimation){
                    this._slideClassHandle();
                }else{
                    this._onTransitionStart(type);
                }
            },
            isHorizontal(){
                return this.direction === HORIZONTAL;
            },
            isVertical(){
                return this.direction === VERTICAL;
            },
            updateEvent(pageSize){
                this.$nextTick(()=>{
                    this.domTimer = setTimeout(()=>{

                        if(pageSize != undefined) this.currentPage = pageSize;
                        this.swiperWrap = this.$el.querySelector('.nut-swiper-wrap');
                        this.slideEls = [...this.swiperWrap.children];
                        if(this.slideEls.length === 0) return;
                        this._getSlideDistance((this.slideEls)[0]);
                        if(this.autoPlay != 0){
                            this.isLoop = true;
                            this._createAutoPlay();
                        }
                        this.isLoop && this._createLoop();
                        this.setPage(this.currentPage, false);
                        this.lazyLoad  && this._imgLazyLoad();
                    },0)

                })
            },
            _slideClassHandle(){
                let selectedSlide = this.$el.querySelector('.nut-swiper-slide-selected');
                selectedSlide && selectedSlide.classList.remove('nut-swiper-slide-selected');
                this.slideEls[this.currentPage -1].classList.add('nut-swiper-slide-selected');
                this.lastPage = this.currentPage;
            },
            _getSlideDistance(el){
                let styleArr = getComputedStyle(el);
                let marginTop = styleArr['marginTop'].replace('px','') - 0;
                let marginBottom = styleArr['marginBottom'].replace('px','') - 0;
                let marginRight = styleArr['marginRight'].replace('px','') - 0;
                let marginLeft = styleArr['marginLeft'].replace('px','') - 0;
                if(this.isHorizontal()){

                    this.oneSlideTranslate = marginRight + marginLeft + el['offsetWidth'];
                }else{
                    this.oneSlideTranslate = marginTop + marginBottom + el['offsetHeight'];
                }
            },
            _onTouchStart(e){
                this.swiperWrap.addEventListener('touchmove',this._onTouchMove,false);
                this.swiperWrap.addEventListener('touchend',this._onTouchEnd,false);
                this.swiperWrap.addEventListener('mousemove',this._onTouchMove,false);
                this.swiperWrap.addEventListener('mouseup',this._onTouchEnd,false);
                this.startPos = this._getTouchPos(e);
                this.delta = 0;
                this.startTranslate = this._getTranslateOfPage(this.currentPage);
                if(this.isLoop){
                    this._setTranslate(this.startTranslate);
                }
                this.startTime = new Date().getTime();
                this.dragging = true;
                this.transitionDuration = 0;
                this.stopAutoPlay = true;
            },
            _onTouchMove(e){
                if(!this.dragging) return;
                if(this.isHorizontal()){
                    this.delta = this._getTouchPos(e).x - this.startPos.x;
                }else{
                    this.delta = this._getTouchPos(e).y - this.startPos.y;
                }
                //let  isQuickAction = (new Date().getTime() - this.startTime) < 200;
                if(this.canDragging && this._computePreventDefault(e)){
                    e.preventDefault();
                    this.lazyLoad && this._imgLazyLoad();
                    this._setTranslate(this.startTranslate + this.delta);
                    this.$emit('slideMove',this._getTranslate(),this.$el);
                }
            },
            _onTouchEnd(e){
                if(!this.dragging) return;
                this.dragging = false;
                this.transitionDuration = this.speed;
                let isQuickAction = new Date().getTime() - this.startTime < 1000;
                if(this.delta < -this.oneSlideTranslate/2 || (isQuickAction && this.delta < -15)){
                    this.next();
                }else if(this.delta > this.oneSlideTranslate/2 || (isQuickAction && this.delta >15)){
                    this.prev();
                }else{
                    this._revert();
                }
                this.swiperWrap.removeEventListener('touchmove',this._onTouchMove,false);
                this.swiperWrap.removeEventListener('touchend',this._onTouchEnd,false);
                this.swiperWrap.removeEventListener('mousemove',this._onTouchMove,false);
                this.swiperWrap.removeEventListener('mouseup',this._onTouchEnd,false);
            },
            _revert(){
                this.setPage(this.currentPage,true);
            },
            _computePreventDefault(e){
                let pos = this._getTouchPos(e);
                let xDis = Math.abs(this.startPos.x - pos.x);
                let yDis = Math.abs(this.startPos.y - pos.y);
                if ( xDis <= 5 && xDis >=0){
                    return false;
                }else if( yDis > 5 && yDis/xDis > 0.5 ){
                    return false;
                }else{
                    return true;
                }
            },
            _getTouchPos(e){
                let x = e.changedTouches ? e.changedTouches[0]['pageX'] :e['pageX'];
                let y = e.changedTouches ? e.changedTouches[0]['pageY'] :e['pageY'];
                return {x,y}
            },
            _onTransitionStart(type){
                this.transitionDuration = this.speed;
                this.lazyLoad && this._imgLazyLoad(1);
                if(this._isPageChanged()){
                    this.$emit('slideChangeStart',this.currentPage,this.$el,type);
                }else{
                    this.$emit('slideRevertStart',this.currentPage,this.$el,type);
                }
            },
            _onTransitionEnd(){
                if(this._isPageChanged()){
                    this.$emit('slideChangeEnd',this.currentPage,this.$el);
                }else{
                    this.$emit('slideRevertEnd',this.currentPage,this.$el);
                }
                this.transitionDuration = 0;
                this.delta = 0;
                this.lastPage = this.currentPage;

                this._slideClassHandle();
                if(this.isLoop){
                    this._setTranslate(this._getTranslateOfPage(this.currentPage));
                }
                this.stopAutoPlay = false;
            },
            _isPageChanged(){
                return this.lastPage !== this.currentPage;
            },
            _setTranslate(value){
                let translateName = this.isHorizontal() ? 'translateX' :'translateY';
                this[translateName] = value;
            },
            _getTranslate(){
                let translateName = this.isHorizontal() ? 'translateX' :'translateY';
                return this[translateName];
            },
            _getTranslateOfPage(page){
                if(page === 0)  return 0;
                let propName = this.isHorizontal() ? 'offsetWidth':'offsetHeight';
                let _this = this;
                return -[].reduce.call(this.slideEls,function(total,el,i){
                    return i> page-2? total : total+_this.oneSlideTranslate;
                },0) + this.translateOffset;
            },
            _createLoop(){
                let propName = this.isHorizontal() ? 'offsetWidth' : 'offsetHeight';
                let swiperWrapEl = this.$el.querySelector('.nut-swiper-wrap');
                let duplicateFirstChild = swiperWrapEl.firstElementChild.cloneNode(true);
                let duplicateLastChild = swiperWrapEl.lastElementChild.cloneNode(true);
                swiperWrapEl.insertBefore(duplicateLastChild,swiperWrapEl.firstElementChild);
                swiperWrapEl.appendChild(duplicateFirstChild);
                this.translateOffset = - this.oneSlideTranslate;
            },
            _createAutoPlay(){
                clearInterval(this.timer);
                this.timer = setInterval(()=>{
                    if(!this.stopAutoPlay){
                        this.next();
                    }
                },this.autoPlay);
            },
            _requestAniFrame(){
                return window.requestAnimationFrame ||
                    window.webkitRequestAnimationFrame ||
                    function(callback){
                        window.setTimeout(callback,1000/60);
                    }
            },
            _imgLazyLoad(type){
                let requestAniFrame = this._requestAniFrame();
                let imgLazyLoadEl;
                requestAniFrame(()=>{
                    imgLazyLoadEl = this.swiperWrap.querySelectorAll('.nut-img-lazyload');
                    if(type == 1){
                        imgLazyLoadEl = this.slideEls[this.currentPage - 1].querySelectorAll('.nut-img-lazyload');
                    }

                    imgLazyLoadEl.forEach((item,index)=>{
                        if(!this._checkInView(item) && type != 1) return;
                        let src = item.getAttribute('data-src');
                        item.src = this.lazyLoadUrl;//jd 图片占位图
                        let img = new Image();
                        img.src = src;
                        img.onload = ()=>{
                            item.src = src;
                            item.classList.remove('nut-img-lazyload');
                        }
                        img.onerror = ()=>{
                            item.src = this.lazyLoadUrl;
                            item.classList.remove('nut-img-lazyload');
                        }

                    })
                })
            },
            _checkInView(imgItem){
                let imgRect = imgItem.getBoundingClientRect();
                let swiperRect = this.$el.getBoundingClientRect();
                let imgTop = imgRect.top;
                let imgLeft = imgRect.left;
                let swiperWidth = this.$el.clientWidth;
                let swiperHeight = this.$el.clientHeight;
                let swiperTop = swiperRect.top;
                let swiperLeft = swiperRect.left;
                let isInView  = true;
                if(imgTop > swiperTop + swiperHeight || imgLeft > swiperLeft + swiperWidth){
                    isInView = false;
                }
                return isInView;
            }

        },
        created(){
        },
        mounted(){


            this._onTouchMove = this._onTouchMove.bind(this);
            this._onTouchEnd = this._onTouchEnd.bind(this);
            this.updateEvent();
        },
        destroyed(){
            this.timer = null;
            this.domTimer = null;
        }
    }
</script>

<style  lang="less" scoped>
    .nut-swiper{
        position: relative;
        overflow: hidden;
        width: 2.816372rem;
        height: 0.768101rem;
        margin: 0.085344rem auto;
    .nut-swiper-wrap{
        display:flex;
        display: -webkit-flex;
        width:100%;
        height:100%;
        transition: all 0ms ease;
        -webkit-transition:all 0ms ease;
    }
    .nut-swiper-slide{
        overflow: hidden;
        flex-shrink: 0;
        -webkit-flex-shrink:0;
        width:100%;
        height:100%;
        cursor: default;
        position: relative;
    }
    &.horizontal .nut-swiper-wrap{
         flex-direction: row;
         -webkit-flex-direction:row;
     }
    &.vertical .nut-swiper-wrap{
         flex-direction: column;
         -webkit-flex-direction:column;
     }
    .nut-swiper-pagination{
        position: absolute;
    .swiper-pagination-bullet{
        display: inline-block;
        width: 0.11947rem;
        height: 0.042667rem;
        margin-right: 0.008533rem;
        background: rgba(75,160,243,0.50);
        transform: skewX(-15deg);
        transition:all .5s ease;
        -webkit-transition:all .5s ease;
        border-radius: 0;

    }
    .swiper-pagination-bullet.active{

        width: 0.204806rem;
        height: 0.042667rem;
        background: #4BA0F3;
        opacity: 1;
    }

    }

    &.vertical .nut-swiper-pagination{
         right:10px;
         top:50%;
         transform:translate3d(0,-50%,0);
         -webkit-transform:translate3d(0,-50%,0);
    .swiper-pagination-bullet{
        display: block;
        margin:6px 0;
    }
    }
    &.horizontal .nut-swiper-pagination{
         bottom:7px;
         width:100%;
         text-align: center;
    .swiper-pagination-bullet{
        display: inline-block;
        margin:0 3px;
    }
    }
    img{
        position: absolute;
        left: 50%;
        margin-left: -45%;
        width: 90%;
        pointer-events: none;
    }
    h3{
        position: absolute;
        top:33%;
        left:0.274rem;
        margin-top: -0.1rem;
        max-width: 14.95rem;
        font-size: 0.11rem;
        line-height: 0.18rem;
        white-space: nowrap;
        text-overflow: ellipsis;
        color:#fff
    }

    }

</style>
